import wx
import wx.lib.agw.aquabutton as AB

from Bio.Blast import NCBIStandalone
from Bio.Blast import NCBIXML
import os

from wx.lib.newevent import NewEvent
(BlastEvent, EVT_START_BLAST) = NewEvent()
(SearchEvent, EVT_START_SEARCH) = NewEvent()

app_path = "D:\\Eigene Datein\\Python\\TIGS DB\\"
source_path = app_path + "files\\"

class StartBlast(wx.Panel):
    def __init__(self, parent):
        """BLAST Panel."""
        wx.Panel.__init__(self, parent, -1)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer = wx.GridBagSizer(hgap=5, vgap=5)

        # Search field
        text = wx.StaticText(self, -1, "Search in TIGS DB by TA-ID or Tube-ID", (8, 10))
        self.search = wx.SearchCtrl(self, size=(200,-1), style=wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_TEXT_ENTER, self.start_search_event, self.search)

        # BLAST stuff
        text2 = wx.StaticText(self, -1, "or BLAST against TIGS DB", (8, 10))
        self.query = wx.TextCtrl(self, size=(400, 100), style=wx.TE_MULTILINE|wx.TE_RICH2|wx.TE_PROCESS_ENTER)
        list = ["Longest sequence database", "RNAi sequence database"]
        self.db = wx.ComboBox(self, 500, "RNAi sequence database", (90, 50),
                         (240, -1), list, wx.CB_DROPDOWN|wx.CB_SORT
                         |wx.CB_READONLY)

        text3 = wx.StaticText(self, -1, "E-Value", (8, 10))
        self.evalue = wx.TextCtrl(self, size=(65, 25))
        text4 = wx.StaticText(self, -1, "Percentage Identity", (8, 10))
        self.percent = wx.TextCtrl(self, size=(65, 25))
        text5 = wx.StaticText(self, -1, "Minimum Hit Length", (8, 10))
        self.length = wx.TextCtrl(self, size=(65, 25))
        # Set values
        self.evalue.SetValue('1e-80')
        self.percent.SetValue('95')
        self.length.SetValue('50')

        # Sizer Options
        vs = wx.BoxSizer(wx.VERTICAL)
        box_title_query = wx.StaticBox(self, -1, "Options")
        box_query = wx.StaticBoxSizer(box_title_query, wx.VERTICAL)
        query_grid = wx.FlexGridSizer(0, 2, 0, 0 )
        self.group_query = []
        self.group_query.append((text3, self.evalue, text4, self.percent, text5, self.length))
        for item1, item2, item3, item4, item5, item6 in self.group_query:
            query_grid.Add(item1, 0, wx.ALIGN_LEFT|wx.LEFT|wx.RIGHT|wx.TOP, 5)
            query_grid.Add(item2, 0, wx.ALIGN_LEFT|wx.LEFT|wx.RIGHT|wx.TOP, 5)
            query_grid.Add(item3, 0, wx.ALIGN_LEFT|wx.LEFT|wx.RIGHT|wx.TOP, 5)
            query_grid.Add(item4, 0, wx.ALIGN_LEFT|wx.LEFT|wx.RIGHT|wx.TOP, 5)
            query_grid.Add(item5, 0, wx.ALIGN_LEFT|wx.LEFT|wx.RIGHT|wx.TOP, 5)
            query_grid.Add(item6, 0, wx.ALIGN_LEFT|wx.LEFT|wx.RIGHT|wx.TOP, 5)
        box_query.Add(query_grid, 0, wx.ALIGN_LEFT|wx.ALL)
        vs.Add(box_query, 0, wx.ALIGN_LEFT|wx.ALL)


        button = AB.AquaButton(self, -1,None, "Start BLAST", size=(120,50))
        self.Bind(wx.EVT_BUTTON, self.start_blast_event)

        # Fonts
        text.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        text2.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        self.search.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        button.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        self.db.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        text3.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        text4.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        text5.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        self.evalue.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        self.percent.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))
        self.length.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL))

        # Sizer
        self.sizer.Add(text, pos=(0, 1))
        self.sizer.Add(self.search, pos=(1, 1))
        self.sizer.Add(text2, pos=(4, 1))
        self.sizer.Add(self.query, pos=(5, 1))
        self.sizer.Add(self.db, pos=(6, 1))
        self.sizer.Add(box_query, pos=(7, 1))

        self.sizer.Add(button, pos=(9, 1))

        mainSizer.Add(self.sizer, 0, wx.ALL, 10)
        self.SetSizer(mainSizer)
        mainSizer.Fit(self)
        mainSizer.SetSizeHints(self)

    def start_search_event(self, evt):
        """Event start search."""
        # Event-Instanz erstellen
        evt = SearchEvent()
        # Event starten
        self.ProcessEvent(evt)

    def start_blast_event(self, evt):
        """Event start BLAST."""
        self.start_blasting()
        # Event-Instanz erstellen
        evt = BlastEvent()
        # Event starten
        self.ProcessEvent(evt)


    def start_blasting(self):
        """Start Blast."""
        f_out = open(source_path + 'blast_result.txt', 'w')
        # Source blastall
        my_blast_exe = "blastall.exe"
        # DB
        if self.db.GetValue() == "Longest sequence database":
            my_blast_db = "rnai_full_length"
        elif self.db.GetValue() == "RNAi sequence database":
            my_blast_db = "rnai_sequence"
        # Query sequence
        seq = self.query.GetValue()
        f_seq = open(source_path + 'query_seq.txt', 'w')
        f_seq.write(seq)
        f_seq.close()
        my_blast_file = "query_seq.txt"
        # Result file
        os.chdir(source_path)
        # Run BLAST with standart paramaters
        result_handle, error_info = NCBIStandalone.blastall(
                    my_blast_exe, 'blastn', my_blast_db, my_blast_file)
        blast_results = result_handle.read()
        save_file = open("my_blast.xml", "w")
        save_file.write(blast_results)
        save_file.close()

        # Save results
        result_handle = open("my_blast.xml")
        blast_records = NCBIXML.parse(result_handle)
        E_VALUE_THRESH = float(self.evalue.GetValue())
        percent = float(self.percent.GetValue())
        length = float(self.length.GetValue())

        for blast_record in blast_records:
            for alignment in blast_record.alignments:
                for hsp in alignment.hsps:
                    percentage_identity = (100.0 * hsp.identities) / hsp.align_length
                    #print E_VALUE_THRESH, hsp.expect, percentage_identity, len(hsp.query)
                    if hsp.expect < E_VALUE_THRESH and percentage_identity > percent and len(hsp.query) > length:
                        f_out.write(str(alignment.hit_def) +
                                     '\t' + str(hsp.align_length) + '\t' +
                                     str(percentage_identity) + '\t' + str(hsp.expect) + '\n')
        f_out.close()